flowchad-runner

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

flowchad-runner

flowchad-runner

Verify named FlowChad flows with Playwright/Navvi, capture per-step screenshot + video evidence, auto-switch to Navvi on CAPTCHA, upload evidence (best-effort), then post results to GitHub and write a local report. Each stage runs as a focused subagent with isolated context. The ICM win here is clean stage contracts + resumability, NOT parallelism: flows CANNOT run concurrently because they share browser, session, and persona state and would collide. Stage 03 walks flows one at a time in a sequential loop.
使用Playwright/Navvi验证指定的FlowChad流程,捕获每一步的截图+视频证据,遇到CAPTCHA时自动切换至Navvi,尽最大努力上传证据,随后将结果发布至GitHub并生成本地报告。每个阶段作为独立上下文的聚焦子Agent运行。此处的核心优势是清晰的阶段契约+可恢复性,而非并行性:流程无法并发运行,因为它们共享浏览器、会话和用户身份状态,会产生冲突。阶段03会按顺序逐个遍历流程

When to Use

适用场景

  • Explicit pre-merge verification for a PR that affects declared flows
  • Production verification after deployment
  • Weekly or scheduled critical production smoke runs
  • Manual local diagnosis when local CAPTCHA behavior is explicitly configured
  • 对影响已声明流程的PR进行明确的合并前验证
  • 部署完成后的生产环境验证
  • 每周或定期执行的关键生产环境冒烟测试
  • 明确配置本地CAPTCHA行为后的手动本地诊断

When Not to Use

不适用场景

  • Docs-only, Dependabot, or unaffected PRs: return
    N/A
    without creating a preview
  • Static-only analysis presented as interactive certification
  • Global provider auto-preview enablement; previews are explicit and on-demand
  • 仅文档变更、Dependabot PR或未影响已声明流程的PR:返回
    N/A
    ,无需创建预览环境
  • 以交互式认证形式呈现的纯静态分析
  • 全局提供商自动预览启用;预览需明确触发且按需创建

Arguments

参数

ParamRequiredDefaultNotes
flow-name
yesFlow name, or
all
(
smoke.critical
for cron;
smoke.flows
otherwise)
repo
yesTarget
org/repo
pr-number
no(none)If set, post results comment to this PR
trigger
no
manual
pr
|
merge
|
cron
|
manual
— drives URL resolution + deploy-wait
Parse positionally from
$ARGUMENTS
:
$1=flow-name $2=repo $3=pr-number $4=trigger
. Use the literal
none
when a cron/manual invocation has no PR number.
ParamRequiredDefaultNotes
flow-name
yesFlow name, or
all
(
smoke.critical
for cron;
smoke.flows
otherwise)
repo
yesTarget
org/repo
pr-number
no(none)If set, post results comment to this PR
trigger
no
manual
pr
|
merge
|
cron
|
manual
— drives URL resolution + deploy-wait
Parse positionally from
$ARGUMENTS
:
$1=flow-name $2=repo $3=pr-number $4=trigger
. Use the literal
none
when a cron/manual invocation has no PR number.

Result Contract

结果契约

StateMeaning
PASSED
Required steps passed with real browser evidence
FAILED
Browser evidence demonstrated a product or flow defect
BLOCKED
A required target, deploy, browser, persona, or credential was unavailable
N/A
PR is docs-only, Dependabot, or does not affect a declared flow
Interactive flows can never pass from curl, static HTML, or bundle inspection. Read references/interactive-contract.md when creating or upgrading
.flowchad/config.yml
and flow definitions.
StateMeaning
PASSED
Required steps passed with real browser evidence
FAILED
Browser evidence demonstrated a product or flow defect
BLOCKED
A required target, deploy, browser, persona, or credential was unavailable
N/A
PR is docs-only, Dependabot, or does not affect a declared flow
交互式流程无法通过curl、静态HTML或包检查来判定通过。创建或升级
.flowchad/config.yml
和流程定义时,请阅读references/interactive-contract.md

What it does

功能说明

5-stage ICM procedure (all sequential — no parallel stages):
StageModeDescription
01-preflightsubagentValidate contract, select affected flow, resolve target/selective preview, deploy-wait, browser/persona check
02-load-flowssubagentRead
.flowchad/config.yml
, validate each flow file exists, load flow YAML
03-walk-flowssubagentSequential loop: for each flow one-at-a-time — connect browser, run steps, per-step screenshot, expect-judgement, CAPTCHA→Navvi, transcript
04-upload-evidencesubagentBest-effort: push screenshots/GIFs to evidence backend, collect URLs
05-reportinlineAggregate results, post PR comment, create issues on failure, write local report, emit outcome marker
5-stage ICM procedure (all sequential — no parallel stages):
StageModeDescription
01-preflightsubagentValidate contract, select affected flow, resolve target/selective preview, deploy-wait, browser/persona check
02-load-flowssubagentRead
.flowchad/config.yml
, validate each flow file exists, load flow YAML
03-walk-flowssubagentSequential loop: for each flow one-at-a-time — connect browser, run steps, per-step screenshot, expect-judgement, CAPTCHA→Navvi, transcript
04-upload-evidencesubagentBest-effort: push screenshots/GIFs to evidence backend, collect URLs
05-reportinlineAggregate results, post PR comment, create issues on failure, write local report, emit outcome marker

Handoff locations

交接位置

All handoffs live in the resolved repo workspace (
$WORKDIR
, see Workspace resolution):
text
$WORKDIR/.procedure-output/flowchad-runner/{stage}/handoff.md
Stage 01 writes the resolved run context (URL, persona, flow list). Each subagent stage receives ONLY the handoff paths its CONTEXT.md lists as inputs — never orchestrator history.
All handoffs live in the resolved repo workspace (
$WORKDIR
, see Workspace resolution):
text
$WORKDIR/.procedure-output/flowchad-runner/{stage}/handoff.md
Stage 01 writes the resolved run context (URL, persona, flow list). Each subagent stage receives ONLY the handoff paths its CONTEXT.md lists as inputs — never orchestrator history.

Execution

执行方式

Run stages strictly sequentially, one after another. There are NO parallel Task launches in this procedure. Spawn exactly one Task per subagent stage and await it before the next.
Run stages strictly sequentially, one after another. There are NO parallel Task launches in this procedure. Spawn exactly one Task per subagent stage and await it before the next.

Workspace resolution (ALWAYS run this first)

Workspace resolution (ALWAYS run this first)

The contract, flows, handoffs, and reports all live inside a checkout of the target repo. Missions run in a workspace that does NOT contain that checkout — never assume the current directory is the repo. Resolve it deterministically before anything else:
bash
SKILL_DIR="$HOME/.claude/skills/flowchad-runner"
[ -d "$SKILL_DIR" ] || SKILL_DIR="$(pwd)/.claude/skills/flowchad-runner"

if [ -f .flowchad/config.yml ]; then
  # Already inside a checkout (local/manual runs)
  WORKDIR="$(pwd)"
else
  REPO_NAME="${REPO##*/}"
  REPO_DIR="/tmp/flowchad-${REPO_NAME}"
  if [ ! -d "$REPO_DIR/.git" ]; then
    # Plain https URL — inline credentials would bypass git-credential-pylot
    git clone "https://github.com/${REPO}.git" "$REPO_DIR" 2>/dev/null \
      || gh repo clone "$REPO" "$REPO_DIR"
  fi
  cd "$REPO_DIR"
  git fetch origin --prune
  if [ "$TRIGGER" = pr ] && [ -n "$PR_NUMBER" ] && [ "$PR_NUMBER" != none ]; then
    # Validate the PR's OWN contract — flows/config may change in the PR itself
    git fetch origin "pull/${PR_NUMBER}/head:flowchad-pr-${PR_NUMBER}" --force
    git checkout -f "flowchad-pr-${PR_NUMBER}"
  else
    DEFAULT_BRANCH=$(gh repo view "$REPO" --json defaultBranchRef -q .defaultBranchRef.name)
    git checkout -f "$DEFAULT_BRANCH"
    git reset --hard "origin/${DEFAULT_BRANCH}"
  fi
  WORKDIR="$REPO_DIR"
fi
[ -f "$WORKDIR/.flowchad/config.yml" ] || {
  echo "[pylot] outcome=\"flowchad blocked: $REPO has no .flowchad/config.yml at the resolved ref\" status=blocked"
  exit 0
}
Every subsequent command (validator, stage handoffs, reports) runs with
cd "$WORKDIR"
. Because subagent Tasks do NOT inherit the orchestrator's
cd
, stage prompts must carry ABSOLUTE paths: substitute the literal values of
$WORKDIR
and
$SKILL_DIR
into the template below — never pass
.claude/...
or
.procedure-output/...
relative forms.
The contract, flows, handoffs, and reports all live inside a checkout of the target repo. Missions run in a workspace that does NOT contain that checkout — never assume the current directory is the repo. Resolve it deterministically before anything else:
bash
SKILL_DIR="$HOME/.claude/skills/flowchad-runner"
[ -d "$SKILL_DIR" ] || SKILL_DIR="$(pwd)/.claude/skills/flowchad-runner"

if [ -f .flowchad/config.yml ]; then
  # Already inside a checkout (local/manual runs)
  WORKDIR="$(pwd)"
else
  REPO_NAME="${REPO##*/}"
  REPO_DIR="/tmp/flowchad-${REPO_NAME}"
  if [ ! -d "$REPO_DIR/.git" ]; then
    # Plain https URL — inline credentials would bypass git-credential-pylot
    git clone "https://github.com/${REPO}.git" "$REPO_DIR" 2>/dev/null \
      || gh repo clone "$REPO" "$REPO_DIR"
  fi
  cd "$REPO_DIR"
  git fetch origin --prune
  if [ "$TRIGGER" = pr ] && [ -n "$PR_NUMBER" ] && [ "$PR_NUMBER" != none ]; then
    # Validate the PR's OWN contract — flows/config may change in the PR itself
    git fetch origin "pull/${PR_NUMBER}/head:flowchad-pr-${PR_NUMBER}" --force
    git checkout -f "flowchad-pr-${PR_NUMBER}"
  else
    DEFAULT_BRANCH=$(gh repo view "$REPO" --json defaultBranchRef -q .defaultBranchRef.name)
    git checkout -f "$DEFAULT_BRANCH"
    git reset --hard "origin/${DEFAULT_BRANCH}"
  fi
  WORKDIR="$REPO_DIR"
fi
[ -f "$WORKDIR/.flowchad/config.yml" ] || {
  echo "[pylot] outcome=\"flowchad blocked: $REPO has no .flowchad/config.yml at the resolved ref\" status=blocked"
  exit 0
}
Every subsequent command (validator, stage handoffs, reports) runs with
cd "$WORKDIR"
. Because subagent Tasks do NOT inherit the orchestrator's
cd
, stage prompts must carry ABSOLUTE paths: substitute the literal values of
$WORKDIR
and
$SKILL_DIR
into the template below — never pass
.claude/...
or
.procedure-output/...
relative forms.

Stages 01 → 04 (sequential subagents)

Stages 01 → 04 (sequential subagents)

For each stage, spawn one Task. The Task prompt must be self-contained:
  • Include only the stage's input handoff paths
  • Include the path to the stage's CONTEXT.md
  • Do NOT pass orchestrator history or prior reasoning
Task prompt template:
text
You are running stage {NN}-{name} of the flowchad-runner procedure.

Workspace: cd {WORKDIR} before any step (absolute path — all relative paths resolve there).

Read your stage instructions:
  {SKILL_DIR}/stages/{NN}-{name}/CONTEXT.md

Your inputs:
  {list each input handoff path this stage needs — absolute, under {WORKDIR}}

Write your output to:
  {WORKDIR}/.procedure-output/flowchad-runner/{NN}-{name}/handoff.md

Execute all steps in CONTEXT.md. Write handoff.md before exiting.
{WORKDIR}
and
{SKILL_DIR}
are the absolute values resolved in Workspace resolution.
Do not start the next stage until the current one completes. If stage 01 cannot resolve a TARGET_URL, or stage 01's deploy-wait fails, or stage 02 finds the flow file missing, emit the matching outcome marker and stop (those stages also create GitHub issues themselves).
Before stage 01, verify the checked-in contract deterministically (from
$WORKDIR
):
bash
cd "$WORKDIR"
mkdir -p .procedure-output/flowchad-runner
MODE="$TRIGGER"
[ "$MODE" = merge ] && MODE=production
[ "$MODE" = pr ] && MODE=preview
[ "$MODE" = manual ] && MODE=local
python3 "$SKILL_DIR/scripts/validate_contract.py" \
  --mode "$MODE" --repo "$REPO" --format json \
  > .procedure-output/flowchad-runner/contract.json
Any validator error blocks production, preview, and cron certification. Do not silently fall back to legacy
.url
, template identity, or localhost for those modes.
For each stage, spawn one Task. The Task prompt must be self-contained:
  • Include only the stage's input handoff paths
  • Include the path to the stage's CONTEXT.md
  • Do NOT pass orchestrator history or prior reasoning
Task prompt template:
text
You are running stage {NN}-{name} of the flowchad-runner procedure.

Workspace: cd {WORKDIR} before any step (absolute path — all relative paths resolve there).

Read your stage instructions:
  {SKILL_DIR}/stages/{NN}-{name}/CONTEXT.md

Your inputs:
  {list each input handoff path this stage needs — absolute, under {WORKDIR}}

Write your output to:
  {WORKDIR}/.procedure-output/flowchad-runner/{NN}-{name}/handoff.md

Execute all steps in CONTEXT.md. Write handoff.md before exiting.
{WORKDIR}
and
{SKILL_DIR}
are the absolute values resolved in Workspace resolution.
Do not start the next stage until the current one completes. If stage 01 cannot resolve a TARGET_URL, or stage 01's deploy-wait fails, or stage 02 finds the flow file missing, emit the matching outcome marker and stop (those stages also create GitHub issues themselves).
Before stage 01, verify the checked-in contract deterministically (from
$WORKDIR
):
bash
cd "$WORKDIR"
mkdir -p .procedure-output/flowchad-runner
MODE="$TRIGGER"
[ "$MODE" = merge ] && MODE=production
[ "$MODE" = pr ] && MODE=preview
[ "$MODE" = manual ] && MODE=local
python3 "$SKILL_DIR/scripts/validate_contract.py" \
  --mode "$MODE" --repo "$REPO" --format json \
  > .procedure-output/flowchad-runner/contract.json
Any validator error blocks production, preview, and cron certification. Do not silently fall back to legacy
.url
, template identity, or localhost for those modes.

Stage 05 (inline)

Stage 05 (inline)

Run stage 05 yourself in the orchestrator. Read CONTEXT.md:
text
.claude/skills/flowchad-runner/stages/05-report/CONTEXT.md
Aggregate the prior handoffs, post the PR comment / create failure issues, write the local report file, and emit the
[pylot] outcome=...
marker from the orchestrator (never a subagent).
Run stage 05 yourself in the orchestrator. Read CONTEXT.md:
text
.claude/skills/flowchad-runner/stages/05-report/CONTEXT.md
Aggregate the prior handoffs, post the PR comment / create failure issues, write the local report file, and emit the
[pylot] outcome=...
marker from the orchestrator (never a subagent).

Stage handoff chain

阶段交接链

text
01-preflight ─► 02-load-flows ─► 03-walk-flows ─► 04-upload-evidence ─► 05-report (inline)
   (URL,            (validated        (sequential        (evidence URLs,        (PR comment,
   persona,          flow YAML)        per-flow walk,     best-effort)           issues, local
   FLOWS_TO_RUN)                       results+transcript)                       report, marker)
text
01-preflight ─► 02-load-flows ─► 03-walk-flows ─► 04-upload-evidence ─► 05-report (inline)
   (URL,            (validated        (sequential        (evidence URLs,        (PR comment,
   persona,          flow YAML)        per-flow walk,     best-effort)           issues, local
   FLOWS_TO_RUN)                       results+transcript)                       report, marker)

Exit paths

退出路径

  • Success: stage 05 emits
    [pylot] outcome="flowchad {flow} on {repo}: all flows passed" status=success
  • Failure: stage 05 emits
    [pylot] outcome="flowchad {flow} on {repo}: {N} flow(s) failed" status=failed
    (failure issues already created in stage 05)
  • Blocked: stage 01 (invalid contract / no URL / deploy failed / no browser) or stage 02 (flow missing) emits
    [pylot] outcome="flowchad blocked: {reason}" status=blocked
    and the chain stops.
  • N/A: stage 01 detects an unaffected/docs-only/Dependabot PR and emits
    [pylot] outcome="flowchad N/A: no affected interactive flow" status=success
    without a deploy.
  • Success: stage 05 emits
    [pylot] outcome="flowchad {flow} on {repo}: all flows passed" status=success
  • Failure: stage 05 emits
    [pylot] outcome="flowchad {flow} on {repo}: {N} flow(s) failed" status=failed
    (failure issues already created in stage 05)
  • Blocked: stage 01 (invalid contract / no URL / deploy failed / no browser) or stage 02 (flow missing) emits
    [pylot] outcome="flowchad blocked: {reason}" status=blocked
    and the chain stops.
  • N/A: stage 01 detects an unaffected/docs-only/Dependabot PR and emits
    [pylot] outcome="flowchad N/A: no affected interactive flow" status=success
    without a deploy.

Hard Rules

硬性规则

  1. All stages run SEQUENTIALLY — exactly one Task at a time, awaited before the next. There is NO parallel fan-out anywhere in this procedure.
  2. Flows are walked ONE AT A TIME inside stage 03 — never one subagent per flow. Flows share browser/session/persona state and would collide if run concurrently.
  3. Stage 05 runs inline — the
    [pylot] outcome=...
    marker MUST come from the orchestrator, never a subagent.
  4. Never pass full orchestrator context into subagent Task prompts — inputs only.
  5. Each stage writes handoff.md before the next stage reads it.
  6. Do not skip stages — every stage executes even if its action is "nothing to do" (e.g. evidence upload with backend
    none
    still writes a handoff).
  7. A broken step is a finding, not a crash — stage 03 continues collecting evidence after a step error; only flow-level pass/fail is judged.
  8. NO Quest, no external dashboards. Reporting = the local report file + GitHub only.
  9. Interactive PASS requires browser evidence. Static/curl diagnostics can support a
    FAILED
    or
    BLOCKED
    result, never
    PASSED
    .
  10. Production-critical controls are never optional or skipped. Missing CAPTCHA/Navvi capability is
    BLOCKED
    , not a pass and not a production skip.
  11. Preview creation is selective. Never enable provider auto-previews; create at most one on-demand preview for an explicitly dispatched relevant PR when no staging target exists.
  12. Cron uses
    smoke.critical
    .
    Failures create or update a deduplicated issue with browser evidence; the public skill does not own the scheduler.
  1. All stages run SEQUENTIALLY — exactly one Task at a time, awaited before the next. There is NO parallel fan-out anywhere in this procedure.
  2. Flows are walked ONE AT A TIME inside stage 03 — never one subagent per flow. Flows share browser/session/persona state and would collide if run concurrently.
  3. Stage 05 runs inline — the
    [pylot] outcome=...
    marker MUST come from the orchestrator, never a subagent.
  4. Never pass full orchestrator context into subagent Task prompts — inputs only.
  5. Each stage writes handoff.md before the next stage reads it.
  6. Do not skip stages — every stage executes even if its action is "nothing to do" (e.g. evidence upload with backend
    none
    still writes a handoff).
  7. A broken step is a finding, not a crash — stage 03 continues collecting evidence after a step error; only flow-level pass/fail is judged.
  8. NO Quest, no external dashboards. Reporting = the local report file + GitHub only.
  9. Interactive PASS requires browser evidence. Static/curl diagnostics can support a
    FAILED
    or
    BLOCKED
    result, never
    PASSED
    .
  10. Production-critical controls are never optional or skipped. Missing CAPTCHA/Navvi capability is
    BLOCKED
    , not a pass and not a production skip.
  11. Preview creation is selective. Never enable provider auto-previews; create at most one on-demand preview for an explicitly dispatched relevant PR when no staging target exists.
  12. Cron uses
    smoke.critical
    .
    Failures create or update a deduplicated issue with browser evidence; the public skill does not own the scheduler.

Reference files

参考文件

  • CONTEXT.md
    — architecture overview
  • stages/NN-name/CONTEXT.md
    — per-stage inputs, task, output contract
  • references/interactive-contract.md
    — target configuration and CAPTCHA/i18n examples
  • scripts/validate_contract.py
    — deterministic environment/flow contract validator
  • CONTEXT.md
    —— 架构概述
  • stages/NN-name/CONTEXT.md
    —— 各阶段的输入、任务、输出契约
  • references/interactive-contract.md
    —— 目标配置和CAPTCHA/i18n示例
  • scripts/validate_contract.py
    —— 确定性环境/流程契约验证器