From pipeline
Verify plan acceptance criteria against a reachable app using browser predicates; emits {satisfied, unsatisfied}. Invoked by execute-issue-plan (TDD loop) and evaluate-issue-pr (verdict).
How this skill is triggered — by the user, by Claude, or both
Slash command
/pipeline:visual-proof-from-planThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Source `pipeline.config` first so `PIPELINE_*` variables are available:
Source pipeline.config first so PIPELINE_* variables are available:
source "$(pwd)/pipeline.config" 2>/dev/null || source ./pipeline.config
# Self-resolve CLAUDE_PLUGIN_ROOT in case the env var is unset in the Bash subshell.
# Anchor via the plugin cache glob (var-independent — no chicken-and-egg dependence on
# CLAUDE_PLUGIN_ROOT to FIND the resolver). _cpr_dir is the dir prefix; literal source line.
_cpr_dir="${CLAUDE_PLUGIN_ROOT:+${CLAUDE_PLUGIN_ROOT}/}"
_cpr_dir="${_cpr_dir:-$(ls -d ${HOME}/.claude/plugins/cache/claude-pipeline-local/pipeline/*/ 2>/dev/null | sort -V | tail -1)}"
_cpr_dir="${_cpr_dir:-$(ls -d ${HOME}/.claude/plugins/cache/claude-pipeline/pipeline/*/ 2>/dev/null | sort -V | tail -1)}"
source "${_cpr_dir}scripts/_resolve-plugin-root.sh" 2>/dev/null || true
Input:
## Implementation Plan comment on issue <N> — this is the
source of acceptance criteria and predicates.APP_BASE_URL). All predicate navigation is resolved relative
to this base.Output: a single JSON object written to stdout. The literal shape is:
{"satisfied": ["<claim>", ...], "unsatisfied": [{"claim": "<string>", "artifact": "<path-or-error>"}, ...]}
satisfied is an array of claim strings whose predicate evaluated truthy.unsatisfied is an array of objects, each pairing the failing claim with an
artifact (a screenshot path on failed assertion, or an error string when the
predicate could not be evaluated).Caller responsibilities:
mcp__playwright_* tools and does not start a browser itself.needs-browser label; do not invoke this skill for
issues that have no reachable UI.execute-issue-plan for the TDD loop, evaluate-issue-pr for the verdict)
decides what the {satisfied, unsatisfied} split means for its own outcome.Predicates are JavaScript expressions evaluated against the live DOM via
mcp__playwright_*browser_evaluate. The expression must return a value that is
truthy when the claim holds. For example:
document.querySelectorAll("#events-table tbody tr").length > 0
A predicate may declare a navigation precondition (a URL to visit before
evaluation). See references/predicate-syntax.md for the full grammar:
querySelector predicates, count predicates, text predicates, and the URL
precondition syntax.
Fetch the latest ## Implementation Plan comment on issue <N>. Extract every
predicate: line that appears under an **Acceptance criteria:** or
**Predicates:** heading. Each extracted line is one claim with one predicate
expression (and an optional navigation precondition — see
references/predicate-syntax.md).
For each predicate:
mcp__playwright_*browser_navigate. If no URL is declared, use the
current page.mcp__playwright_*browser_evaluate with the predicate expression..claude/scratch/visual-proof-<N>/<predicate-hash>.png for evidence.satisfied; a falsy value or
an evaluation error is unsatisfied (record the screenshot path or the error
string as the artifact).Write the single JSON object described in ## Contract to stdout:
{"satisfied": ["<claim>", ...], "unsatisfied": [{"claim": "<string>", "artifact": "<path-or-error>"}, ...]}
{satisfied, unsatisfied}
split is evidence; callers (execute-issue-plan, evaluate-issue-pr) own the
decision.npx claudepluginhub rjskene/pipeline --plugin pipelineCreates bite-sized, testable implementation plans from specs or requirements, with file structure and task decomposition. Activates before coding multi-step tasks.