Skip to content
Back to skills

Journeys Verify

ASecurity

Verifies that docs/journeys/*.md spec files (written by journeys-extract) still hold true — every source_ref path still exists and every test_id is still findable in the repo's test suite. Runs a cheap deterministic script (Tier 1, safe for CI/pre-commit on every PR) that flips each journey's status between draft/verified/stale, plus an optional LLM semantic-drift pass (Tier 2, per journey, checks whether the narrative still matches the actual UI/code) for a fuller review. Use to check journe...

  • 8 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 20, 2026
ai-agentsrustbashnodegit

Security analysis

A100/100

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

Scanned September 20, 2026

npx -y skills add tstapler/dotfiles --skill journeys-verify --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Journeys Verify?

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

Security grade badge for Journeys Verify
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tstapler-journeys-verify/badge)](https://www.skillsdirectory.com/skills/tstapler-journeys-verify)

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: journeys-verify
description: >
  Verifies that docs/journeys/*.md spec files (written by journeys-extract) still
  hold true — every source_ref path still exists and every test_id is still
  findable in the repo's test suite. Runs a cheap deterministic script (Tier 1,
  safe for CI/pre-commit on every PR) that flips each journey's status between
  draft/verified/stale, plus an optional LLM semantic-drift pass (Tier 2, per
  journey, checks whether the narrative still matches the actual UI/code) for a
  fuller review. Use to check journeys are still accurate — for a quick CI gate
  ("is anything broken"), or before trusting a journey doc during onboarding or
  planning. Does not discover new journeys (journeys-extract) or improve/deepen
  journey content (journeys-enrich).
---

# Journeys: Verify

Check that persisted journey specs (`docs/journeys/*.md`) still describe reality.
Two tiers: a deterministic script that checks mechanical links (fast, CI-safe,
no LLM judgment needed), and an optional LLM pass per journey that checks whether
the step narrative still matches the actual UI/code (slower, judgment-based).

## When to Use

- CI/pre-commit gate: fail the build if any journey is stale (Tier 1 only)
- Before relying on `docs/journeys/` for onboarding, planning, or a PR review —
  confirm it's not lying
- After `journeys-extract` flags journeys `updated-marked-stale`, to confirm
  whether the drift is real or the linked tests just moved
- NOT for discovering journeys that don't exist yet (`journeys-extract`) or for
  writing/improving journey narrative (`journeys-enrich`)

## Input

```
/journeys:verify [--strict] [--full]
```

- `--strict`: exit 1 if any journey ends up `stale` (for CI gating)
- `--full`: also run the Tier 2 semantic-drift pass (default: Tier 1 only)

## Tier 1 — Deterministic (always runs)

```bash
uv run .claude/skills/journeys-verify/scripts/verify_journeys.py check --strict
```

For every `docs/journeys/*.md` file (except `README.md`), this script:
- Checks every `source_refs` path still exists on disk
- Checks every `test_ids` string is still findable as a full-text substring
  somewhere in the repo (excluding `.git`, `node_modules`, `dist`, `build`,
  `.venv`, `__pycache__`, and `docs/journeys/` itself)
- Sets `status`: `verified` if both checks pass and `test_ids` is non-empty;
  `stale` if either check fails; `draft` if `test_ids` is empty (nothing to
  verify yet — not a failure)
- Sets `last_verified` to today's date only when `status` becomes `verified`
- Records why in `verify_notes` (a list of reason strings)
- Never touches `title`, `user_types`, `source_refs`, or the body — those are
  extraction-owned

Read the script's JSON output (`{results: [...], counts: {...}}`) directly —
don't re-derive counts by hand.

## Tier 2 — Semantic Drift (only with `--full`)

For each journey the script left `verified` (mechanical links hold), spawn one
lean agent per journey **in parallel** to check whether the narrative still
matches reality — this is the check no script can do:

```
Read the journey spec at <path>. Read its source_refs files (and the UI/code
they point to). Compare the journey's numbered Steps against what the code/UI
actually does today.

Does the narrative still accurately describe the flow? Consider: renamed
screens/buttons referenced in a step, steps that no longer trigger the way
described, missing steps for new required fields, dead-end states not reflected
in the diagram.

Return ONLY this JSON:
{
  "slug": "<journey_id>",
  "still_accurate": true|false,
  "drift_notes": ["specific mismatch, if any"]
}
```

For any journey where `still_accurate: false`, update its `status` to `stale`
and append `drift_notes` to `verify_notes` — do this directly with the Edit tool
on just those two frontmatter fields (don't touch anything else in the file, and
don't re-run Tier 1's script afterward or it will silently overwrite your edit
based on stale in-memory assumptions — apply Tier 2 edits last).

## Pre-commit / CI Integration

`scripts/pre-commit-hook.sh` wraps Tier 1 for git hooks: it no-ops if the repo
has no `docs/journeys/` (safe to install anywhere), runs `verify_journeys.py
check --strict`, and blocks the commit if status changed (needs re-staging) or
any journey is still stale. Requires `uv` on `PATH`.

**Install into a target repo** (fresh hook):
```bash
ln -s "$(pwd)/.claude/skills/journeys-verify/scripts/pre-commit-hook.sh" .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
```

**Append to an existing hook** instead of overwriting it:
```bash
echo '.claude/skills/journeys-verify/scripts/pre-commit-hook.sh || exit 1' >> .git/hooks/pre-commit
```

**CI (any runner)** — same script, minus the git-diff staging check, run non-strict
in normal jobs and `--strict` as a merge gate:
```bash
uv run .claude/skills/journeys-verify/scripts/verify_journeys.py check --strict
```

**jj-colocated repos**: `jj` does not reliably invoke `.git/hooks/pre-commit` the
way plain git does — verify this on the target repo before relying on it; if it
doesn't fire, wire the same command into CI instead.

## Reporting

Tell the user: counts per status (verified/stale/draft), and for any stale
journey, its `verify_notes` reasons. If `--strict` and CI failed, name which
journeys blocked it. Do NOT dump full journey files into the conversation —
counts + reasons are enough for a decision.

## Anti-Patterns

- **Don't hand-edit `status`/`last_verified`/`verify_notes` outside this skill** —
  they're recomputed here; manual edits get silently overwritten on the next run.
- **Don't run Tier 2 on every CI invocation** — it's LLM-driven and not free;
  reserve `--full` for periodic review or explicit request, keep CI on Tier 1.
- **Don't treat `draft` as a failure** — a journey with no `test_ids` yet is
  expected during early adoption; that's `journeys-enrich`'s job to fix, not a
  verify failure. Only gate CI on `stale`.

Files in this skill

  • SKILL.md5.8 KB
  • scripts/pre-commit-hook.sh1.2 KB
  • scripts/verify_journeys.py6.6 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…